/*! \file eval_expr.c
 *  \brief Expression evaluation using Shunting-Yard algorithm 
 *  \author Lluis Garrido
 *
 *  This file contains the functions for evaluating a mathematical 
 *  expression contained in a string. Only two functions are to be
 *  called by the user, namely
 *  - ::eval_expr_shunting_yard Transforms a mathematical expression
 *    contained in a string into a reverse polish notation.
 *  - ::eval_expr_evaluation  Given the reverse polish notation of
 *    a mathematical expression, it evaluates it to obtain the numerical
 *    result.
 *
 *  All remaining functions are used internally by the above two functions
 *  and should not be called directly by the user (unless you really know
 *  what you are doing).
 *
 *  The code shown here is an adaption of the code of the following web page:
 *  http://en.wikipedia.org/wiki/Shunting_yard_algorithm. 
 */

#include "eval_expr.h"

/*! \def IS_COMMA     
 *  \brief Used for parsing the mathematical expression in function ::eval_expr_shunting_yard. Checks if character c is a comma.
 */ 
#define IS_COMMA(c)        (c == ',')
/*! \def IS_NEGATIVE  
 *  \brief Used for parsing the mathematical expression in function ::eval_expr_shunting_yard. Checks if character c is the negative sign.  
 */ 
#define IS_NEGATIVE(c)     (c == '-')
/*! \def IS_OPERATOR  
 *  \brief Used for parsing the mathematical expression in function ::eval_expr_shunting_yard. Checks if character is an operator (+,-,/,*). 
 */
#define IS_OPERATOR(c)     (c == '+' || c == '-' || c == '/' || c == '*') 
/*! \def IS_LPARENTHESIS  
 *  \brief Used for parsing the mathematical expression in function ::eval_expr_shunting_yard. Checks if character is a left parenthesis. 
 */
#define IS_LPARENTHESIS(c) (c == '(')
/*! \def IS_RPARENTHESIS  
 *  \brief Used for parsing the mathematical expression in function ::eval_expr_shunting_yard. Checks if character is a right parenthesis. 
 */
#define IS_RPARENTHESIS(c) (c == ')')

/*! \def OP_NONE 
 *  \brief Used internally in eval_expr.c to identify operators. This is the identifier associated to no operation 
 */
#define OP_NONE            0
/*! \def OP_PLUS
 *  \brief Used internally in eval_expr.c to identify operators. This is the identifier associated to the plus (+) sign 
 */
#define OP_PLUS            1
/*! \def OP_MINUS
 *  \brief Used internally in eval_expr.c to identify operators. This is the identifier associated to the plus (-) sign 
 */
#define OP_MINUS           2
/*! \def OP_PRODUCT
 *  \brief Used internally in eval_expr.c to identify operators. This is the identifier associated to the product (*) sign 
 */
#define OP_PRODUCT         3
/*! \def OP_DIVIDE
 *  \brief Used internally in eval_expr.c to identify operators. This is the identifier associated to the division (/) sign 
 */
#define OP_DIVIDE          4
/*! \def OP_NEGATIVE
 *  \brief Used internally in eval_expr.c to identify operators. This is the identifier associated to the negative (-) sign 
 */
#define OP_NEGATIVE        5

#ifndef NDEBUG
  static char *op_name[] =
    {"", "Plus", "Minus", "Product", "Divide", "Equal", "Negative"};
#endif

/*! 
 *  \brief Applies an operator to numerical arguments
 *
 *  This function is called internally by ::eval_expr_evaluation.
 *
 *  \param[in] operator_id The identifier associated to the operator (may be OP_PLUS,
 *                         OP_MINUS, OP_PRODUCT, OP_DIVIDE, OP_NEGATIVE)
 *  \param[in] arguments   The numerical arguments needed to evaluate the operator.
 *
 *  \return The result of applying the operator to the arguments. For instance, 
 *          if operator_id == OP_PLUS then the return value is arguments[0] + arguments[1].
 * 
 *  See also ::eval_expr_get_operator_id
 */

double eval_expr_evaluate_operator(int operator_id, double *arguments)
{
  double ret = 0;

  switch (operator_id)
  {
    case OP_PLUS:
      ret = arguments[0] + arguments[1];
      break;

    case OP_MINUS:
      ret = arguments[0] - arguments[1];
      break;

    case OP_PRODUCT:
      ret = arguments[0] * arguments[1];
      break;

    case OP_DIVIDE:
      if (arguments[1] == 0.0)
      {
	printf("ERROR: division by zero.\n");
	exit(EXIT_FAILURE);
      }

      ret = arguments[0] / arguments[1];
      break;

    case OP_NEGATIVE:
      ret = - arguments[0];
      break;
  }

  return ret;
}

/*! 
 *  \brief Gets the identifier (an integer number) associated to the operator 
 *
 *  This function is called internally by ::eval_expr_shunting_yard.
 *
 *  \param[in] operator    A character identifying the operator: '+','-','/','*' or '!'
 *
 *  \return  The identifier associated to the operator: OP_PLUS, OP_MINUS,
 *           OP_DIVIDE, OP_PRODUCT, OP_NEGATIVE respectively.
 *
 *  Note that the '!' character is associated to OP_NEGATIVE. Indeed, the
 *  ::eval_expr_shunting_yard algorithm is able to distinguish between the '-'
 *  associated to a difference as in "4-5" and the '-' associated to the
 *  negative sign, as in 'Sin(-4)'. When ::eval_expr_shunting_yard calls this
 *  function it uses '-' to indicate OP_MINUS, and '!' when a negative sign is
 *  detected.
 * 
 *  See also ::eval_expr_evaluate_operator
 */

int eval_expr_get_operator_id(char operator)
{
  int ret;

  ret = OP_NONE;

  if (operator == '+')
    ret = OP_PLUS;
  else if (operator == '-')
    ret = OP_MINUS;
  else if (operator == '*')
    ret = OP_PRODUCT;
  else if (operator == '/')
    ret = OP_DIVIDE;
  else if (operator == '!')
    ret = OP_NEGATIVE;

  assert(ret != OP_NONE);

  return ret;
}

/*! 
 *  \brief Gets operator precedence
 *
 *  This function is called internally by ::eval_expr_shunting_yard.
 *
 *  \param[in] operator   The identifier associated to the operator : OP_PLUS, OP_MINUS, 
 *                        OP_DIVIDE, OP_PRODUCT, OP_NEGATIVE respectively.
 *
 *  \return The operator precedence. The higher the value the higher the precedence.
 *
 *  Currently the precedence is set as follows: OP_NEGATIVE has precedence 3,
 *  OP_DIVIDE and OP_PRODUCT have precedence 2, OP_PLUS and OP_MIN_US have
 *  precedence 1. This means that, e.g. in the expression 1+2*3 the product has
 *  precedence over the sum.
 *  
 */

int eval_expr_operator_precedence(int operator)
{
  switch (operator)    
  {
    case OP_NEGATIVE:
      return 3;

    case OP_PRODUCT:  
    case OP_DIVIDE: 
      return 2;

    case OP_PLUS: 
    case OP_MINUS:
      return 1;
  }

  return 0;
}

/*! 
 *  \brief Gets operator associativity
 *
 *  This function is called internally by ::eval_expr_shunting_yard.
 *
 *  \param[in] operator   The identifier associated to the operator : OP_PLUS,
 *                        OP_MINUS, OP_DIVIDE, OP_PRODUCT, OP_NEGATIVE respectively.
 *
 *  \return The operator associativity. Returns ::TRUE if operator is left associative, 
 *          and ::FALSE if operator is right associative.
 *
 *  Currently the associativity is set as follows: OP_NEGATIVE is right
 *  associative, whereas all remaining operators are left associative. This
 *  means that e.g., 1+2+3 is computed as (1+2)+3, or 1+2-3 is computed as
 *  (1+2)-3.  
 *  
 */

BOOL eval_expr_is_operator_left_associative(int operator)
{
  switch (operator)    
  {
    // left to right
    case OP_PRODUCT: 
    case OP_DIVIDE: 
    case OP_PLUS: 
    case OP_MINUS:
      return TRUE;

      // right to left
    case OP_NEGATIVE: 
      return FALSE;
  }

  return FALSE;
}

/*! 
 *  \brief Gets number of arguments for each operator.
 *
 *  This function is called internally by ::eval_expr_shunting_yard.
 *
 *  \param[in] operator   The identifier associated to the operator : OP_PLUS,
 *                        OP_MINUS, OP_DIVIDE, OP_PRODUCT, OP_NEGATIVE respectively.
 *
 *  \return The number of arguments for the operator. 
 *
 *  Currently the number of arguments for each operator is: OP_NEGATIVE has
 *  one argument, wheres the remaining ones have two arguments. For instance,
 *  the OP_PLUS has two arguments in the expression 4+6. The arguments are 4
 *  and 6. 
 *  
 */

unsigned int eval_expr_arg_count_operator(int operator)
{
  switch (operator)  
  {
    case OP_PRODUCT: 
    case OP_DIVIDE:
    case OP_PLUS:
    case OP_MINUS:
      return 2;

    case OP_NEGATIVE:
      return 1;
  }

  return 0;
}

/*! 
 *  \brief Extracts a number from a string. 
 *
 *  This function is called internally by ::eval_expr_shunting_yard.
 *
 *  \param[in] init_pos    The initial position from which the number is
 *                         extracted.
 *  \param[out] end_pos    A pointer to the character afeter the last character
 *                         used in the conversion. 
 *
 *  \return The extracted number.
 *
 *  This function performs internal checking to ensure that that
 *  the number is well formed.
 *
 *  For example, assume the expression 1+3.9452*4.212. If init_pos
 *  points to the character '3', then this function will return 
 *  3.9452 and end_pos will point to the character '*'.
 *
 *  See also ::eval_expr_get_string
 *  
 */

double eval_expr_get_number(char *init_pos, char **end_pos)
{
  double number;

  errno  = 0;

  // convert ASCII string to floating-point number (see man's page)
  number = strtod(init_pos, end_pos);

  if ((errno == ERANGE && (number == HUGE_VAL || number == -HUGE_VAL))
      || ((errno != 0) & (number == 0))) 
  {
    perror("strtod");
    exit(EXIT_FAILURE);
  }

  if (init_pos == *end_pos)
  {
    printf("ERROR: no digits where found\n");
    exit(EXIT_FAILURE);
  }

  return number;
}

/*! 
 *  \brief Extracts an alpha-numerical string from a string. 
 *
 *  A string is formed by alpha-numerical characters, that is, 
 *  'a'-'z','A'-'Z' and '0' to '9'.  
 *
 *  This function is called internally by ::eval_expr_shunting_yard.
 *
 *  \param[in] init_pos    The initial position from which the number is
 *                         extracted.
 *  \param[out] string     The extracted string terminating with a null
 *                         character. The string has to be previously 
 *                         allocated with a minimum size of MAX_SIZE_VARIABLE. 
 *  \param[out] end_pos    A pointer to the character afeter the last character
 *                         used in the conversion. 
 *
 *  This function performs internal checking to ensure that that
 *  the string is well formed.
 *
 *  For example, assume the expression 1+pi*4. If we call the
 *  function with init_pos pointing to the 'p', then the function
 *  output will be as follows: string will contain 'pi' (with a
 *  terminating null character) and end_pos will point to '*'.
 *
 *  See also ::eval_expr_get_number
 *  
 */

void eval_expr_get_string(char *init_pos, char *string, char **end_pos)
{
  char *pos = (char *) init_pos;
  int i     = 0;
  int max_i = MAX_SIZE_VARIABLE - 2;

  do
  {
    if (i >= max_i)
    {
      printf("ERROR: variable or function identifier is too long\n");
      exit(EXIT_FAILURE);
    }

    string[i] = *pos;
    i++;
    pos++;
  }
  while (isalnum(*pos));

  // Set the null terminating character
  string[i] = '\0';

  *end_pos = pos;
}

/*! 
 *  \brief Applies the Shunting Yard algorithm to an infix expression. 
 *
 *  This function takes an input string expression and applies the
 *  Shunting Yard algorithm to obtain a postfix expression. The
 *  algorithm does not numerically evaluate the expression. For that 
 *  you need to call ::eval_expr_evaluation. 
 *
 *  \param[in] input       The input infix expression to be converted.
 *  \param[in] param       Parameters associated to the evaluation of
 *                         the expression. 
 *  \param[out] stack_rpn  The postfix notation of the input expression.
 *                         
 *  For example, assume the input expression 1+pi*4. The output of the
 *  function, stored in param, would be (1, (pi, 4) *) +
 *
 *  The code is based on the code shown on web page
 *  http://en.wikipedia.org/wiki/Shunting-yard_algorithm
 *
 */

void eval_expr_shunting_yard(char *input,  struct eval_expr_param *param, struct rpn_stack *stack_rpn)
{
  struct rpn_stack_item *el;
  struct rpn_stack *stack_operator;

  BOOL start_expression;

  double number;
  char name[MAX_SIZE_VARIABLE];
 
  int nargs;
  int index_function = -1;
  int nargs_function[MAX_STACK_LENGTH];

   char *strpos = input, *strend = input + strlen(input);
  char *endpos;

  char c;

  stack_operator = rpn_stack_allocate(MAX_STACK_LENGTH);

  start_expression  = TRUE;

  while (strpos < strend)   
  {
    // read one token from the input stream
    c  = *strpos;

    if (!isspace(c))    
    {
      if (c == '!')
      {
	printf("Unknown token %c\n", c);
	exit(EXIT_FAILURE); // Unknown token
      }

      if ((start_expression) && IS_NEGATIVE(c))
      {
	c = '!';
	start_expression = FALSE;
      }

      // If the token is a number, then add it to the stack_rpn queue.
      if (isdigit(c))  
      {
	number = eval_expr_get_number(strpos, &endpos);
	rpn_stack_insert_number(stack_rpn, number);
	strpos = endpos;

	start_expression = FALSE;
      }
      // If the token is a variable name, then seek for it and add it's value to the stack_rpn queue
      else if (islower(c))
      {
	int id;

	eval_expr_get_string(strpos, name, &endpos);

	id = list_variables_get_variable_id(param->lva, name); 

	if (id == VARIABLE_ID_NONE)
	{
	  printf("ERROR: variable %s does not exist.\n", name);
	  exit(EXIT_FAILURE);
	}

	rpn_stack_insert_variable(stack_rpn, id);

	strpos = endpos;

	start_expression  = FALSE;
      }
      // If the token is a function token, then push it onto the stack_operator.
      else if (isupper(c))   
      {
	int id;

	// We'll use nargs_function[index_function]
	// in order to count the number of arguments
	// that are passed to the function. For that
	// issue the number of commas "," have to
	// be counted. See condition IS_COMMA below.

	index_function++;
	nargs_function[index_function] = 1;

	// Get the name of the function 
	eval_expr_get_string(strpos, name, &endpos);

	// Check if the function exists. 'id' is the
	// function identifier
	id = list_functions_get_function_id(param->lfu, name);

	if (id == FUNCTION_ID_NONE)
	{
	  printf("ERROR: function %s not defined.\n", name);
	  exit(EXIT_FAILURE);
	}

	rpn_stack_insert_function(stack_operator, id);

	strpos = endpos;

	start_expression  = FALSE;
      }
      // If the token is a function argument separator (e.g., a comma):
      else if (IS_COMMA(c))   
      {
	// Increment the number of arguments that are passed to the
	// function. 

	nargs_function[index_function]++;

	BOOL pe = FALSE;
	while (stack_operator->currel > 0)   
	{
	  if (rpn_stack_get_previous_type_item(stack_operator) == RPN_TYPE_LPARENTHESIS)  
	  {
	    pe = TRUE;
	    break;
	  }
	  else  
	  {
	    // Until the token at the top of the stack_operator is a left parenthesis,
	    // pop operators off the stack_operator onto the stack_rpn queue.
	    rpn_stack_pop_and_insert_one_item(stack_rpn, stack_operator);
	  }
	}

	// If no left parentheses are encountered, either the separator was misplaced
	// or parentheses were mismatched.
	if (!pe)   
	{
	  printf("Error: separator or parentheses mismatched.\n");
	  exit(EXIT_FAILURE);
	}

	strpos++;
	start_expression = TRUE;
      }
      // If the token is an operator op1 or a negative sign then:
      else if (IS_OPERATOR(c) | (c == '!'))  
      {
	int op1, op2;

	op1 = eval_expr_get_operator_id(c);

	while (stack_operator->currel > 0)    
	{
	  if (rpn_stack_get_previous_type_item(stack_operator) == RPN_TYPE_OPERATOR)
	  {
	    op2 = stack_operator->el[stack_operator->currel - 1].value.operator_id;
	    // While there is an operator token, op2, at the top of the stack_operator
	    // op1 is left-associative and its precedence is less than or equal to that of op2,
	    // or op1 is right-associative and its precedence is less than that of op2,
	    if ((eval_expr_is_operator_left_associative(op1) && (eval_expr_operator_precedence(op1) <= eval_expr_operator_precedence(op2))) ||
		(!eval_expr_is_operator_left_associative(op1) && (eval_expr_operator_precedence(op1) < eval_expr_operator_precedence(op2))))  
	    {
	      // Pop op2 off the stack_operator, onto the stack_rpn queue;
	      rpn_stack_pop_and_insert_one_item(stack_rpn, stack_operator);
	    }
	    else 
	    {
	      break;
	    }
	  }
	  else
	  {
	    // In case previous item is a function or a parenthesis
	    break;
	  }
	}
	// Push op1 onto the stack_operator.
	rpn_stack_insert_operator(stack_operator, op1);

	strpos++;
	start_expression = TRUE;
      }
      // If the token is a left parenthesis, then push it onto the stack_operator.
      else if (IS_LPARENTHESIS(c))
      {
	rpn_stack_insert_lparenthesis(stack_operator);
	strpos++;
	start_expression = TRUE;
      }
      // If the token is a right parenthesis:
      else if (IS_RPARENTHESIS(c))    
      {
	BOOL pe = FALSE;
	// Until the token at the top of the stack_operator is a left parenthesis,
	// pop operators off the stack_operator onto the stack_rpn queue
	while (stack_operator->currel > 0)     
	{
	  if (rpn_stack_get_previous_type_item(stack_operator) == RPN_TYPE_LPARENTHESIS)    
	  {
	    pe = TRUE;
	    break;
	  }
	  else  
	    rpn_stack_pop_and_insert_one_item(stack_rpn, stack_operator);
	}
	// If the stack_operator runs out without finding a left parenthesis, 
	// then there are mismatched parentheses.
	if (!pe)  
	{
	  printf("ERROR: parentheses mismatched.\n");
	  exit(EXIT_FAILURE); 
	}
	// Pop the left parenthesis from the stack_operator, but not onto the stack_rpn queue.
	stack_operator->currel--;
	// If the token at the top of the stack_operator is a function token, pop it onto the stack_rpn queue.
	if(stack_operator->currel > 0)   
	{
	  if (rpn_stack_get_previous_type_item(stack_operator) == RPN_TYPE_FUNCTION)
	  {
	    // Check if the number of arguments that are
	    // passed to the function in the 'input' string
	    // coincides with the number of arguments the
	    // function admits. 

	    el    = rpn_stack_get_previous_item(stack_operator); 
	    nargs = list_functions_get_arg_count(param->lfu, el->value.function_id);

	    if (nargs != nargs_function[index_function])
	    {
	      printf("ERROR: incorrect number of arguments for function %s.\n", list_functions_get_name(param->lfu, el->value.function_id));
	      exit(EXIT_FAILURE);
	    }

	    rpn_stack_pop_and_insert_one_item(stack_rpn, stack_operator);

	    // Decrement this index since there may be
	    // recursive function calls, such as Pow(Sin(1.0), 2.0).

	    index_function--;
	  }
	}
	strpos++;
      }
      else  
      {
	printf("Unknown token %c\n", c);
	exit(EXIT_FAILURE); // Unknown token
      }
    }
  }
  // When there are no more tokens to read and
  // while there are still operator tokens in the stack_operator
  while (stack_operator->currel > 0)  
  {
    if (rpn_stack_get_previous_type_item(stack_operator) == RPN_TYPE_LPARENTHESIS)
    {
      printf("ERROR: parentheses mismatched.\n");
      exit(EXIT_FAILURE); 
    }

    rpn_stack_pop_and_insert_one_item(stack_rpn, stack_operator);
  }

  rpn_stack_free(stack_operator);
}

/*! 
 *  \brief Evaluates a postfix expression numerically. 
 *
 *  This function takes as input an expression in postfix
 *  notation (see ::eval_expr_shunting_yard) and evaluates
 *  it numerically.
 *
 *  \param[in] param       Parameters associated to the evaluation of
 *                         the expression. 
 *  \param[in] stack_rpn   The postfix notation of the expression, obtained
 *                         with ::eval_expr_shunting_yard.
 *
 *  \return The numerical result of evaluating the expression.
 *                         
 *  For example, assume the input expression 1+pi*4. After calling
 *  ::eval_expr_shunting_yard, stack_rpn would store the expression
 *  as (1, (pi, 4) *) +. Then ::eval_expr_evaluation is called and
 *  the final result is obtained: 13.566371.
 *
 *  The code is based on the code shown on web page
 *  http://en.wikipedia.org/wiki/Shunting-yard_algorithm
 *
 */



double eval_expr_evaluation(struct eval_expr_param *param, struct rpn_stack *stack_rpn) 
{
  struct rpn_stack_item *el;

  double partial_result = 0.0;
  double arguments[MAX_ARGUMENTS];

  int index_stack = 0;
  double stack[MAX_STACK_LENGTH];

  int index = 0, i;

#ifndef NDEBUG
  char *function_name = NULL;
  int currel = 1;
  int stack_id[MAX_STACK_LENGTH];
  int arguments_id[MAX_ARGUMENTS];
#endif

  // While there are input tokens left
  while (index < stack_rpn->currel)  
  {
    // Read the token from input.
    el = rpn_stack_get_item(stack_rpn, index);
    // If the token is a value or identifier
    if (el->type_item == RPN_TYPE_NUMBER)    
    {
      // Push it onto the stack.
      stack[index_stack] = el->value.number;

#ifndef NDEBUG
      stack_id[index_stack] = currel;
      printf("_%02d = %f\n", currel, stack[index_stack]);
      currel++;
#endif

      index_stack++;
    }
    else if (el->type_item == RPN_TYPE_VARIABLE)
    {
      stack[index_stack] = list_variables_get_value(param->lva, el->value.variable_id);

#ifndef NDEBUG
      stack_id[index_stack] = currel;
      printf("_%02d = %s = %f\n", currel, list_variables_get_name(param->lva, el->value.variable_id), stack[index_stack]);
      currel++;
#endif

      index_stack++;
    }
    // Otherwise, the token is an operator (operator here includes both operators and functions).
    else 
    {
      unsigned int nargs = 0;

      if (el->type_item == RPN_TYPE_OPERATOR)     
      {
	// Get the number of arguments of the operator 
	nargs = eval_expr_arg_count_operator(el->value.operator_id);

#ifndef NDEBUG
	function_name = op_name[el->value.operator_id];
#endif

	// Pop the top nargs values from the stack.
	for(i = 0; i < nargs; i++)
	{
	  if (index_stack == 0)
	  {
	    printf("ERROR: incorrect expression.\n");
	    exit(EXIT_FAILURE);
	  }

	  arguments[nargs - 1 - i] = stack[index_stack - 1];
#ifndef NDEBUG
	  arguments_id[nargs - 1 - i] = stack_id[index_stack - 1];
#endif
	  index_stack--;
	}

	// Evaluate the operator, with arguments.
	partial_result = eval_expr_evaluate_operator(el->value.operator_id, arguments);

      }

      if (el->type_item == RPN_TYPE_FUNCTION) 
      {
	// Get the number of arguments of the function
	nargs = list_functions_get_arg_count(param->lfu, el->value.function_id);

#ifndef NDEBUG
	function_name = list_functions_get_name(param->lfu, el->value.function_id);
#endif

	// Pop the top nargs values from the stack.
	for(i = 0; i < nargs; i++)
	{
	  assert(index_stack != 0);

	  arguments[nargs - 1 - i] = stack[index_stack - 1];
#ifndef NDEBUG
	  arguments_id[nargs - 1 - i] = stack_id[index_stack - 1];
#endif
	  index_stack--;
	}

	// Evaluate the function, with arguments
	partial_result = list_functions_evaluate(param->lfu, el->value.function_id, arguments);
      }

#ifndef NDEBUG
      stack_id[index_stack] = currel;
      printf("_%02d = %s(", currel, function_name);
      for(i = 0; i < nargs-1; i++)
      {
	printf("_%02d = %f,", arguments_id[i], arguments[i]);
      }
      printf("_%02d = %f)", arguments_id[i], arguments[i]);
      printf(" = %f\n", partial_result);
      currel++;
#endif

      // Push the returned results back onto the stack.
      stack[index_stack] = partial_result; 
      index_stack++;
    }

    index++;
  }

  // If there is only one value in the stack
  // That value is the result of the calculation.
  if (index_stack == 1) 
    return stack[0];

  // If there are more values in the stack
  // (Error) The user input has too many values.
  printf("ERROR: incorrect expression. Some operands may be missing.\n");
  exit(EXIT_FAILURE);

  return 0;
}


